<template>
  <div class="page-container">
    <div id="app" ref="app">
      <div
        v-for="(item, index) in renderList"
        :id="`${item.name}`"
        :ref="`${item.name}`"
        :key="index"
        :style="itemStyle(item)"
        class="item">
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'WaterfallFlow', // 瀑布流
  data () {
    return {
      currentImgIndex: 0, // 当前的渲染索引
      renderList: [], // 渲染数据列表
      allList: [
        { width: 1920, height: 1080 },
        { width: 640, height: 720 },
        { width: 720, height: 680 },
        { width: 720, height: 1920 },
        { width: 900, height: 600 },
        { width: 400, height: 300 },
        { width: 2048, height: 1920 },
        { width: 700, height: 900 },
        { width: 1600, height: 900 },
        { width: 200, height: 200 },
      ], // 所有数据列表
      columns: 3, // 渲染列数
      tempArr: [] // 列高度的数组
    };
  },
  mounted() {
    this.tempArr = new Array(this.columns).fill(0);
    this.getList();
  },
  methods: {
    randomColor () {
      const r = Math.floor(Math.random() * 255);
      const g = Math.floor(Math.random() * 255);
      const b = Math.floor(Math.random() * 255);
      return `rgb(${r},${g},${b})`;
    },
    itemStyle(item) {
      return `width:${item.width};height:${item.height};backgroundColor:${item.backgroundColor};transform:translate(${item.minHeightIndex * 100}%, ${item.minHeight}px)`;
    },
    getList() {
      const obj = this.getItemInfo();
      this.$nextTick(() => {
        const dom = this.$refs[obj.name][0];
        const observer = new IntersectionObserver((entries) => {
          if (entries[0].isIntersecting) {  // 如果已进入视图，停止监听，并且生成新的元素
            observer.unobserve(dom);
            this.getList();
          }
        });
        this.tempArr[obj.minHeightIndex] += dom.offsetHeight;
        observer.observe(dom);
      });
    },
    getItemInfo() {
      const domSizeIndex = Math.floor(Math.random() * this.allList.length);
      const size = this.allList[domSizeIndex];
      const minHeight = Math.min(...this.tempArr); // 列最小高度
      const minHeightIndex = this.tempArr.indexOf(minHeight); // 列最小高度的索引

      const obj = {
        name: `item${this.currentImgIndex}`,
        width: `${Math.floor(100 / this.columns)}%`, // 宽度为百分比
        height: `${300 / size.width * size.height}px`, // 高度为默认高度与实际宽高的比例
        backgroundColor: this.randomColor(),
        minHeight,
        minHeightIndex
      };
      this.renderList.push(obj);

      const app = this.$refs.app;
      const maxHeight = Math.max(...this.tempArr); // 列最大高度
      app.style.height = maxHeight + 'px';

      this.currentImgIndex++;
      return obj;
    },
  }
};
</script>

<style scoped lang="scss">
#app {
  position: relative;
  width: 100%;
  margin: auto;
}
.item {
  position: absolute;
  border-radius: 20px;
  border: 10px solid black;
  box-sizing: border-box;
  text-align: center;
  color: white;
}
</style>
